from libc.stdint cimport uint64_t as u64, uint32_t as u32, uint8_t as u8, uint16_t as u16, int32_t as i32,\
    int16_t as i16, int8_t as i8, int64_t as i64, UINT64_MAX, UINT32_MAX, UINT16_MAX, INT64_MAX, INT64_MIN, UINT32_MAX, UINT8_MAX
include 'hashset.pyx'
cdef u64 DAY_US=1000*1000*60*60*24, HOUR_US=1000*1000*60*60, MINUTE_US=1000*1000*60, SECOND_US=1000*1000, MS_US=1000
cdef u64[12] MOONTH_DAYS = [31*DAY_US,59*DAY_US,90*DAY_US,120*DAY_US,151*DAY_US,181*DAY_US,212*DAY_US,243*DAY_US,273*DAY_US,304*DAY_US,334*DAY_US,365*DAY_US]
cdef u64[12] LEAP_MOONTH_DAYS = [31*DAY_US,60*DAY_US,91*DAY_US,121*DAY_US,152*DAY_US,182*DAY_US,213*DAY_US,244*DAY_US,274*DAY_US,305*DAY_US,335*DAY_US,366*DAY_US]
cdef u64[4] YEARS_us = [365*DAY_US,365*2*DAY_US,365*3*DAY_US,(365*4+1)*DAY_US]
cdef u64 FOUR_YEAR_us = (365*4+1)*DAY_US

cdef inline u64 year(u64 t, u64* moon, u64* remain):
    cdef uint eq
    cdef u64 four=<u64>(t/FOUR_YEAR_us), mod=<u64>(t%FOUR_YEAR_us), y
    cdef u64 i, m, r
    cdef u64* moons
    if mod < YEARS_us[0]:
        y=four*4+1
        r = t- (four*FOUR_YEAR_us)
        m = bisect_u64(MOONTH_DAYS, r, 12, &eq)
    elif mod < YEARS_us[3]:
        for i in range(1,3):
            if mod<YEARS_us[i]:
                y=(four<<2)+i+1
                r = t- (four*FOUR_YEAR_us+YEARS_us[i-1])
                m = bisect_u64(MOONTH_DAYS, r, 12, &eq)
        raise AssertionError
    else:
        y = (four << 2) + 3
        r = t - (four * FOUR_YEAR_us + YEARS_us[2])
        m = bisect_u64(LEAP_MOONTH_DAYS, r, 12, &eq)
    remain[0]=r
    moon[0]=m
    return y
cdef inline u64 day(u64 t,):
    return div(t, DAY_US)
cdef inline u64 hour(u64 t,):
    return div(t, HOUR_US)
cdef inline u64 min(u64 t,):
    return div(t, MINUTE_US)
cdef inline u64 sec(u64 t,):
    return div(t, SECOND_US)
cdef inline u64 ms(u64 t,):
    return div(t, MS_US)

cdef class  Date:
    cdef u64 time
